/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    eeprom.c
  * @brief   EEPROM读写模块实现
  *          支持AT24C系列EEPROM芯片的I2C通信
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "eeprom.h"

/* Private variables ---------------------------------------------------------*/
static uint8_t eeprom_initialized = 0;

/* Private function prototypes -----------------------------------------------*/
static HAL_StatusTypeDef EEPROM_WaitForReady(void);

/**
 * @brief  EEPROM初始化
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_Init(void)
{
    HAL_StatusTypeDef status;
    
    // 检查EEPROM是否响应
    status = EEPROM_IsReady();
    if (status == HAL_OK)
    {
        eeprom_initialized = 1;
    }
    
    return status;
}

/**
 * @brief  检查EEPROM是否就绪
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_IsReady(void)
{
    return HAL_I2C_IsDeviceReady(EEPROM_I2C_HANDLE, EEPROM_DEVICE_ADDR, 3, EEPROM_TIMEOUT);
}

/**
 * @brief  等待EEPROM就绪(写操作后)
 * @retval HAL_StatusTypeDef 状态
 */
static HAL_StatusTypeDef EEPROM_WaitForReady(void)
{
    HAL_Delay(EEPROM_WRITE_DELAY);
    return EEPROM_IsReady();
}

/**
 * @brief  从EEPROM读取单个字节
 * @param  addr: 读取地址
 * @param  data: 数据指针
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_ReadByte(uint16_t addr, uint8_t *data)
{
    if (!eeprom_initialized || data == NULL || addr >= EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    uint8_t mem_addr = (uint8_t)addr;
    return HAL_I2C_Mem_Read(EEPROM_I2C_HANDLE, EEPROM_DEVICE_ADDR, mem_addr, 
                           I2C_MEMADD_SIZE_8BIT, data, 1, EEPROM_TIMEOUT);
}

/**
 * @brief  向EEPROM写入单个字节
 * @param  addr: 写入地址
 * @param  data: 要写入的数据
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_WriteByte(uint16_t addr, uint8_t data)
{
    HAL_StatusTypeDef status;
    
    if (!eeprom_initialized || addr >= EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    uint8_t mem_addr = (uint8_t)addr;
    status = HAL_I2C_Mem_Write(EEPROM_I2C_HANDLE, EEPROM_DEVICE_ADDR, mem_addr,
                              I2C_MEMADD_SIZE_8BIT, &data, 1, EEPROM_TIMEOUT);
    
    if (status == HAL_OK)
    {
        status = EEPROM_WaitForReady();
    }
    
    return status;
}

/**
 * @brief  从EEPROM读取多个字节
 * @param  addr: 起始地址
 * @param  data: 数据缓冲区指针
 * @param  size: 读取字节数
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_ReadBytes(uint16_t addr, uint8_t *data, uint16_t size)
{
    if (!eeprom_initialized || data == NULL || (addr + size) > EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    uint8_t mem_addr = (uint8_t)addr;
    return HAL_I2C_Mem_Read(EEPROM_I2C_HANDLE, EEPROM_DEVICE_ADDR, mem_addr,
                           I2C_MEMADD_SIZE_8BIT, data, size, EEPROM_TIMEOUT);
}

/**
 * @brief  向EEPROM写入多个字节
 * @param  addr: 起始地址
 * @param  data: 数据缓冲区指针
 * @param  size: 写入字节数
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_WriteBytes(uint16_t addr, uint8_t *data, uint16_t size)
{
    HAL_StatusTypeDef status = HAL_OK;
    uint16_t bytes_written = 0;
    uint16_t current_addr = addr;
    uint8_t page_remaining;
    uint8_t write_size;
    
    if (!eeprom_initialized || data == NULL || (addr + size) > EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    while (bytes_written < size && status == HAL_OK)
    {
        // 计算当前页剩余空间
        page_remaining = EEPROM_PAGE_SIZE - (current_addr % EEPROM_PAGE_SIZE);
        
        // 确定本次写入大小
        write_size = (size - bytes_written) > page_remaining ? page_remaining : (size - bytes_written);
        
        // 页写入
        status = EEPROM_WritePage(current_addr, &data[bytes_written], write_size);
        
        if (status == HAL_OK)
        {
            bytes_written += write_size;
            current_addr += write_size;
        }
    }
    
    return status;
}

/**
 * @brief  页写入(提高写入效率)
 * @param  addr: 起始地址
 * @param  data: 数据缓冲区指针
 * @param  size: 写入字节数(不超过页大小)
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_WritePage(uint16_t addr, uint8_t *data, uint8_t size)
{
    HAL_StatusTypeDef status;
    
    if (!eeprom_initialized || data == NULL || size > EEPROM_PAGE_SIZE || 
        (addr + size) > EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    uint8_t mem_addr = (uint8_t)addr;
    status = HAL_I2C_Mem_Write(EEPROM_I2C_HANDLE, EEPROM_DEVICE_ADDR, mem_addr,
                              I2C_MEMADD_SIZE_8BIT, data, size, EEPROM_TIMEOUT);
    
    if (status == HAL_OK)
    {
        status = EEPROM_WaitForReady();
    }
    
    return status;
}

/**
 * @brief  擦除EEPROM(写入0xFF)
 * @param  addr: 起始地址
 * @param  size: 擦除字节数
 * @retval HAL_StatusTypeDef 状态
 */
HAL_StatusTypeDef EEPROM_Erase(uint16_t addr, uint16_t size)
{
    HAL_StatusTypeDef status = HAL_OK;
    uint8_t erase_data[EEPROM_PAGE_SIZE];
    uint16_t bytes_erased = 0;
    uint8_t erase_size;
    
    if (!eeprom_initialized || (addr + size) > EEPROM_MAX_SIZE)
    {
        return HAL_ERROR;
    }
    
    // 填充擦除数据
    for (uint8_t i = 0; i < EEPROM_PAGE_SIZE; i++)
    {
        erase_data[i] = 0xFF;
    }
    
    while (bytes_erased < size && status == HAL_OK)
    {
        erase_size = (size - bytes_erased) > EEPROM_PAGE_SIZE ? EEPROM_PAGE_SIZE : (size - bytes_erased);
        
        status = EEPROM_WriteBytes(addr + bytes_erased, erase_data, erase_size);
        
        if (status == HAL_OK)
        {
            bytes_erased += erase_size;
        }
    }
    
    return status;
}